using System;
using System.Collections.Generic;
using System.Text;

namespace OracleInternal.I18N
{
	[Serializable]
	internal class TLBConv12Byte : TLBConv
	{
		protected delegate int ConvertByteToCharsDelegate<T>(byte[] bytes, int byteOffsets, int byteCounts, T[] chars, int charOffset, ref int charCount, bool bUseReplacementChar);

		private const int ORACHARMASK = 255;

		private const int UCSCHARWIDTH = 16;

		private const int ORACHARWIDTH = 16;

		protected const int BYTEWIDTH = 8;

		protected short MAX_7_8_BIT = 127;

		protected static int MAXLIMIT = 42000;

		public char[] m_ucsCharLevel1;

		public int[] m_ucsCharLevel2;

		public int m_ucsCharReplacement;

		public int[] m_oraCharLevel1;

		public int[] m_oraCharSurrogateLevel;

		public char[] m_oraCharLevel2;

		public char m_1ByteOraCharReplacement;

		public char[] m_2ByteOraCharReplacement = new char[2];

		public override int MinBytesPerChar => 1;

		public override int MaxBytesPerChar => 2;

		public TLBConv12Byte()
		{
			m_groupId = 1;
		}

		protected int ToUnicode(int srcChar, bool ccb)
		{
			int num = (srcChar >> 8) & 0xFF;
			int num2 = srcChar & 0xFF;
			if (m_ucsCharLevel1[num] != '\uffff' && m_ucsCharLevel2[m_ucsCharLevel1[num] + num2] != 65535)
			{
				return m_ucsCharLevel2[m_ucsCharLevel1[num] + num2];
			}
			if (ccb)
			{
				return m_ucsCharReplacement;
			}
			throw new DecoderFallbackException(I18nStringResourceManager.GetErrorMesg("FAIL_CONV_TO_UNICODE"));
		}

		private int ToUnicodeNoException(int srcChar)
		{
			int num = (srcChar >> 8) & 0xFF;
			int num2 = srcChar & 0xFF;
			if (m_ucsCharLevel1[num] != '\uffff')
			{
				return m_ucsCharLevel2[m_ucsCharLevel1[num] + num2];
			}
			return 65535;
		}

		protected char ToOracleCharacter(char srcChar, char lowSurrogate, bool ccb)
		{
			char c = '\uffff';
			if (lowSurrogate != 0)
			{
				int num = ((int)srcChar >> 8) & 0xFF;
				int num2 = srcChar & 0xFF;
				int num3 = ((int)lowSurrogate >> 8) & 0xFF;
				int num4 = lowSurrogate & 0xFF;
				if (m_oraCharLevel1[num] != 65535 && m_oraCharSurrogateLevel[m_oraCharLevel1[num] + num2] != 65535 && m_oraCharSurrogateLevel[m_oraCharSurrogateLevel[m_oraCharLevel1[num] + num2] + num3] != 65535 && m_oraCharLevel2[m_oraCharSurrogateLevel[m_oraCharSurrogateLevel[m_oraCharLevel1[num] + num2] + num3] + num4] != '\uffff')
				{
					c = m_oraCharLevel2[m_oraCharSurrogateLevel[m_oraCharSurrogateLevel[m_oraCharLevel1[num] + num2] + num3] + num4];
				}
			}
			else
			{
				int num5 = ((int)srcChar >> 8) & 0xFF;
				int num6 = srcChar & 0xFF;
				if (m_oraCharLevel1[num5] != 65535 && m_oraCharLevel2[m_oraCharLevel1[num5] + num6] != '\uffff')
				{
					c = m_oraCharLevel2[m_oraCharLevel1[num5] + num6];
				}
			}
			if (c == '\uffff')
			{
				if (!ccb)
				{
					throw new DecoderFallbackException(I18nStringResourceManager.GetErrorMesg("FAIL_CONV_TO_BYTES"));
				}
				if (srcChar > '\u2fff')
				{
					return m_2ByteOraCharReplacement[0];
				}
				return m_1ByteOraCharReplacement;
			}
			return c;
		}

		public override void BuildUnicodeToOracleMapping()
		{
			m_oraCharLevel1 = new int[256];
			m_oraCharSurrogateLevel = null;
			m_oraCharLevel2 = null;
			IList<int[]> list = new List<int[]>(45055);
			Dictionary<int, char[]> dictionary = new Dictionary<int, char[]>();
			Dictionary<int, char[]> dictionary2 = new Dictionary<int, char[]>();
			int num = 0;
			int num2 = 0;
			for (int i = 0; i < 256; i++)
			{
				m_oraCharLevel1[i] = 65535;
			}
			for (int j = 0; j < 65535; j++)
			{
				int num3;
				if ((num3 = ToUnicodeNoException(j)) != 65535)
				{
					list.Add(new int[2]
					{
						num3,
						j
					});
					StoreMappingRange(num3, dictionary, dictionary2);
				}
			}
			int num4;
			if (extraUnicodeToOracleMapping != null)
			{
				num4 = extraUnicodeToOracleMapping.Length;
				for (int k = 0; k < num4; k++)
				{
					int ucsCodePt = extraUnicodeToOracleMapping[k][0];
					StoreMappingRange(ucsCodePt, dictionary, dictionary2);
				}
			}
			int num5 = 0;
			int num6 = 0;
			foreach (KeyValuePair<int, char[]> item in dictionary)
			{
				if (item.Value != null)
				{
					num5 += 256;
				}
			}
			foreach (KeyValuePair<int, char[]> item2 in dictionary2)
			{
				if (item2.Value != null)
				{
					num6 += 256;
				}
			}
			if (num5 != 0)
			{
				m_oraCharSurrogateLevel = new int[num5];
			}
			if (num6 != 0)
			{
				m_oraCharLevel2 = new char[num6];
			}
			for (int l = 0; l < num5; l++)
			{
				m_oraCharSurrogateLevel[l] = 65535;
			}
			for (int m = 0; m < num6; m++)
			{
				m_oraCharLevel2[m] = '\uffff';
			}
			for (int n = 0; n < list.Count; n++)
			{
				int[] array = list[n];
				int num7 = (array[0] >> 24) & 0xFF;
				int num8 = (array[0] >> 16) & 0xFF;
				int num9 = (array[0] >> 8) & 0xFF;
				int num10 = array[0] & 0xFF;
				if (num7 >= 216 && num7 < 220)
				{
					if (m_oraCharLevel1[num7] == 65535)
					{
						m_oraCharLevel1[num7] = num2;
						num2 += 256;
					}
					if (m_oraCharSurrogateLevel[m_oraCharLevel1[num7] + num8] == 65535)
					{
						m_oraCharSurrogateLevel[m_oraCharLevel1[num7] + num8] = num2;
						num2 += 256;
					}
					if (m_oraCharSurrogateLevel[m_oraCharSurrogateLevel[m_oraCharLevel1[num7] + num8] + num9] == 65535)
					{
						m_oraCharSurrogateLevel[m_oraCharSurrogateLevel[m_oraCharLevel1[num7] + num8] + num9] = num;
						num += 256;
					}
					if (m_oraCharLevel2[m_oraCharSurrogateLevel[m_oraCharSurrogateLevel[m_oraCharLevel1[num7] + num8] + num9] + num10] == '\uffff')
					{
						m_oraCharLevel2[m_oraCharSurrogateLevel[m_oraCharSurrogateLevel[m_oraCharLevel1[num7] + num8] + num9] + num10] = (char)((uint)array[1] & 0xFFFFu);
					}
				}
				else
				{
					if (m_oraCharLevel1[num9] == 65535)
					{
						m_oraCharLevel1[num9] = num;
						num += 256;
					}
					if (m_oraCharLevel2[m_oraCharLevel1[num9] + num10] == '\uffff')
					{
						m_oraCharLevel2[m_oraCharLevel1[num9] + num10] = (char)((uint)array[1] & 0xFFFFu);
					}
				}
			}
			if (extraUnicodeToOracleMapping == null)
			{
				return;
			}
			num4 = extraUnicodeToOracleMapping.Length;
			for (int num11 = 0; num11 < num4; num11++)
			{
				int ucsCodePt = extraUnicodeToOracleMapping[num11][0];
				int num7 = (ucsCodePt >> 24) & 0xFF;
				int num8 = (ucsCodePt >> 16) & 0xFF;
				int num9 = (ucsCodePt >> 8) & 0xFF;
				int num10 = ucsCodePt & 0xFF;
				if (num7 >= 216 && num7 < 220)
				{
					if (m_oraCharLevel1[num7] == 65535)
					{
						m_oraCharLevel1[num7] = num2;
						num2 += 256;
					}
					if (m_oraCharSurrogateLevel[m_oraCharLevel1[num7] + num8] == 65535)
					{
						m_oraCharSurrogateLevel[m_oraCharLevel1[num7] + num8] = num2;
						num2 += 256;
					}
					if (m_oraCharSurrogateLevel[m_oraCharSurrogateLevel[m_oraCharLevel1[num7] + num8] + num9] == 65535)
					{
						m_oraCharSurrogateLevel[m_oraCharSurrogateLevel[m_oraCharLevel1[num7] + num8] + num9] = num;
						num += 256;
					}
					m_oraCharLevel2[m_oraCharSurrogateLevel[m_oraCharSurrogateLevel[m_oraCharLevel1[num7] + num8] + num9] + num10] = (char)((uint)extraUnicodeToOracleMapping[num11][1] & 0xFFFFu);
				}
				else
				{
					if (m_oraCharLevel1[num9] == 65535)
					{
						m_oraCharLevel1[num9] = num;
						num += 256;
					}
					m_oraCharLevel2[m_oraCharLevel1[num9] + num10] = (char)((uint)extraUnicodeToOracleMapping[num11][1] & 0xFFFFu);
				}
			}
		}

		public override void ExtractCodepoints(IList<int[]> vtable)
		{
			int num = 65535;
			for (int i = 0; i <= num; i++)
			{
				try
				{
					vtable.Add(new int[2]
					{
						i,
						ToUnicode(i, ccb: true)
					});
				}
				catch
				{
				}
			}
		}

		public override void ExtractExtraMappings(IList<int[]> vtable)
		{
			if (extraUnicodeToOracleMapping != null)
			{
				for (int i = 0; i < extraUnicodeToOracleMapping.Length; i++)
				{
					vtable.Add(new int[2]
					{
						extraUnicodeToOracleMapping[i][0],
						extraUnicodeToOracleMapping[i][1]
					});
				}
			}
		}

		public override bool HasExtraMappings()
		{
			return extraUnicodeToOracleMapping != null;
		}

		public override char GetOraChar1ByteRep()
		{
			return m_1ByteOraCharReplacement;
		}

		public override char GetOraChar2ByteRep()
		{
			return m_2ByteOraCharReplacement[0];
		}

		public override int GetUCS2CharRep()
		{
			return m_ucsCharReplacement;
		}

		public override bool IsOraCharacterReplacement(char ch, char lowsur)
		{
			char c = ToOracleCharacter(ch, lowsur, ccb: true);
			if (c != GetOraChar1ByteRep())
			{
				return c == GetOraChar2ByteRep();
			}
			return true;
		}

		public override int GetBytesLength(char[] chars, int charOffset, int charCount)
		{
			int num = charOffset;
			int num2 = charOffset + charCount;
			char c = '\uffff';
			int num3 = 0;
			if (num < 0)
			{
				num = 0;
			}
			if (num2 > chars.Length)
			{
				num2 = chars.Length;
			}
			for (int i = num; i < num2; i++)
			{
				if (chars[i] >= '\ud800' && chars[i] < '\udc00')
				{
					if (i + 1 >= num2 || chars[i + 1] < '\udc00' || chars[i + 1] > '\udfff')
					{
						num3 += 2;
						continue;
					}
					c = ToOracleCharacter(chars[i], chars[i + 1], ccb: true);
					i++;
				}
				else
				{
					c = ToOracleCharacter(chars[i], '\0', ccb: true);
				}
				num3 = (((int)c >> 8 == 0) ? (num3 + 1) : (num3 + 2));
			}
			return num3;
		}

		public override int GetBytesLength(string chars, int charOffset, int charCount)
		{
			int num = charOffset;
			int num2 = charOffset + charCount;
			char c = '\uffff';
			int num3 = 0;
			if (num < 0)
			{
				num = 0;
			}
			if (num2 > chars.Length)
			{
				num2 = chars.Length;
			}
			for (int i = num; i < num2; i++)
			{
				if (chars[i] >= '\ud800' && chars[i] < '\udc00')
				{
					if (i + 1 >= num2 || chars[i + 1] < '\udc00' || chars[i + 1] > '\udfff')
					{
						num3 += 2;
						continue;
					}
					c = ToOracleCharacter(chars[i], chars[i + 1], ccb: true);
					i++;
				}
				else
				{
					c = ToOracleCharacter(chars[i], '\0', ccb: true);
				}
				num3 = (((int)c >> 8 == 0) ? (num3 + 1) : (num3 + 2));
			}
			return num3;
		}

		public override int GetBytesLength(byte[] utf16Bytes, int utf16BytesOffset, int utf16BytesCount)
		{
			int num = utf16BytesOffset;
			int num2 = utf16BytesOffset + utf16BytesCount;
			if (num < 0)
			{
				num = 0;
			}
			if (num2 > utf16Bytes.Length)
			{
				num2 = utf16Bytes.Length;
			}
			char c = '\uffff';
			int num3 = 0;
			for (int i = num; i < num2 - 1; i += 2)
			{
				int num4 = (utf16Bytes[i + 1] << 8) | utf16Bytes[i];
				if (num4 >= 55296 && num4 < 56320)
				{
					if (i + 3 >= num2)
					{
						num3 += 2;
						continue;
					}
					int num5 = (utf16Bytes[i + 3] << 8) | utf16Bytes[i + 2];
					if (num5 >= 56320 && num5 <= 57343)
					{
						c = ToOracleCharacter((char)num4, (char)num5, ccb: true);
						i++;
					}
				}
				else
				{
					c = ToOracleCharacter((char)num4, '\0', ccb: true);
				}
				num3 = (((int)c >> 8 == 0) ? (num3 + 1) : (num3 + 2));
			}
			return num3;
		}

		protected virtual int GetCharsLengthImpl(byte[] bytes, int offset, int count, ref int bytesCounted)
		{
			int i = offset;
			int num = offset + count;
			if (num > bytes.Length)
			{
				num = bytes.Length;
			}
			int num2 = 0;
			for (; i < num; i++)
			{
				int num3 = bytes[i] & 0xFF;
				if (num3 > MAX_7_8_BIT)
				{
					if (i >= num - 1)
					{
						bytesCounted = i - offset;
						break;
					}
					num3 = ((bytes[i] << 8) & 0xFF00) | (bytes[i + 1] & 0xFF);
					i++;
				}
				int num4 = (num3 >> 8) & 0xFF;
				int num5 = num3 & 0xFF;
				int num6 = ((m_ucsCharLevel1[num4] == '\uffff' || m_ucsCharLevel2[m_ucsCharLevel1[num4] + num5] == 65535) ? m_ucsCharReplacement : m_ucsCharLevel2[m_ucsCharLevel1[num4] + num5]);
				num2 = (((num6 & 0xFFFFFFFFu) <= 65535) ? (num2 + 1) : (num2 + 2));
			}
			bytesCounted = i - offset;
			return num2;
		}

		public override int GetCharsLength(byte[] bytes, int byteOffset, int byteCount)
		{
			int bytesCounted = 0;
			return GetCharsLengthImpl(bytes, byteOffset, byteCount, ref bytesCounted);
		}

		protected virtual int GetBytesOffsetImpl(byte[] bytes, int offset, int count, ref int charCount)
		{
			int i = offset;
			int num = offset + count;
			int num2 = 0;
			if (num > bytes.Length)
			{
				num = bytes.Length;
			}
			for (; i < num; i++)
			{
				if (num2 >= charCount)
				{
					break;
				}
				int num3 = bytes[i] & 0xFF;
				if (num3 > MAX_7_8_BIT)
				{
					if (i >= num - 1)
					{
						break;
					}
					num3 = ((bytes[i] << 8) & 0xFF00) | (bytes[i + 1] & 0xFF);
					i++;
				}
				int num4 = (num3 >> 8) & 0xFF;
				int num5 = num3 & 0xFF;
				int num6 = ((m_ucsCharLevel1[num4] == '\uffff' || m_ucsCharLevel2[m_ucsCharLevel1[num4] + num5] == 65535) ? m_ucsCharReplacement : m_ucsCharLevel2[m_ucsCharLevel1[num4] + num5]);
				num2 = (((num6 & 0xFFFFFFFFu) <= 65535) ? (num2 + 1) : (num2 + 2));
			}
			charCount = num2;
			return i - offset;
		}

		public override int GetBytesOffset(byte[] bytes, int byteOffset, int byteCount, int charCount)
		{
			int charCount2 = charCount;
			return GetBytesOffsetImpl(bytes, byteOffset, byteCount, ref charCount2);
		}

		public override int GetCharsLength(ArraySegment<byte> bytes, int bytesOffset, int bytesCount)
		{
			int bytesCounted = 0;
			return GetCharsLengthImpl(bytes.Array, bytes.Offset + bytesOffset, bytesCount, ref bytesCounted);
		}

		public override int GetCharsLength(IList<ArraySegment<byte>> bytes, int bytesOffset, int bytesCount)
		{
			int num = 0;
			int bytesCounted = 0;
			int num2 = 0;
			int num3 = 0;
			byte[] array = null;
			int num4 = 0;
			int idx = 0;
			int offSet = bytes[0].Offset;
			bool flag = false;
			if (bytesOffset > 0)
			{
				UTF16ConvUtility.GetSegementIndices(bytes, bytesOffset, ref idx, ref offSet);
			}
			for (int i = idx; i < bytes.Count; i++)
			{
				if (flag)
				{
					break;
				}
				int num5 = bytes[i].Offset + num3;
				int num6 = bytes[i].Count - num3;
				if (i == idx)
				{
					num5 = offSet + num3;
					num6 = bytes[i].Count - (offSet - bytes[i].Offset) - num3;
				}
				if (bytesCount - num2 <= num6)
				{
					num6 = bytesCount - num2;
					flag = true;
				}
				int charsLengthImpl = GetCharsLengthImpl(bytes[i].Array, num5, num6, ref bytesCounted);
				num += charsLengthImpl;
				num2 += bytesCounted;
				if (bytesCounted < num6 && !flag && i < bytes.Count - 1)
				{
					if (array == null)
					{
						array = new byte[2];
					}
					byte[] array2 = bytes[i + 1].Array;
					int num7 = num5 + bytesCounted;
					array[0] = bytes[i].Array[num7];
					array[1] = array2[bytes[i + 1].Offset];
					num3 = 1;
					num4 = 2;
					charsLengthImpl = GetCharsLengthImpl(array, 0, num4, ref bytesCounted);
					num += charsLengthImpl;
					num2 += bytesCounted;
				}
				else
				{
					num3 = 0;
				}
			}
			return num;
		}

		public override int GetBytesOffset(IList<ArraySegment<byte>> bytes, int charCount)
		{
			int charCount2 = charCount;
			int num = 0;
			int num2 = 0;
			int num3 = 0;
			byte[] array = null;
			int num4 = 0;
			for (int i = 0; i < bytes.Count; i++)
			{
				if (num >= charCount)
				{
					break;
				}
				int num5 = bytes[i].Offset + num3;
				int num6 = bytes[i].Count - num3;
				byte[] array2 = bytes[i].Array;
				int bytesOffsetImpl = GetBytesOffsetImpl(array2, num5, num6, ref charCount2);
				num2 += bytesOffsetImpl;
				num += charCount2;
				charCount2 = charCount - num;
				if (charCount2 > 0 && bytesOffsetImpl < num6 && i < bytes.Count - 1)
				{
					if (array == null)
					{
						array = new byte[2];
					}
					byte[] array3 = bytes[i + 1].Array;
					int num7 = num5 + bytesOffsetImpl;
					array[0] = array2[num7];
					array[1] = array3[bytes[i + 1].Offset];
					num3 = 1;
					num4 = 2;
					bytesOffsetImpl = GetBytesOffsetImpl(array, 0, num4, ref charCount2);
					num2 += bytesOffsetImpl;
					num += charCount2;
					charCount2 = charCount - num;
				}
				else
				{
					num3 = 0;
				}
			}
			return num2;
		}

		public override int ConvertBytesToChars(byte[] bytes, int offset, int count, char[] chars, int charOffset, ref int charCount, bool ccb)
		{
			int i = offset;
			if (i < 0)
			{
				i = 0;
			}
			int num = i + count;
			if (num > bytes.Length)
			{
				num = bytes.Length;
			}
			int num2 = charOffset;
			if (num2 < 0)
			{
				num2 = 0;
			}
			int num3 = num2 + charCount;
			if (num3 > chars.Length)
			{
				num3 = chars.Length;
			}
			for (; i < num; i++)
			{
				if (num2 >= num3)
				{
					break;
				}
				bool flag = false;
				int num4 = bytes[i] & 0xFF;
				if (num4 > MAX_7_8_BIT)
				{
					if (i >= num - 1)
					{
						if (ccb)
						{
							break;
						}
						throw new DecoderFallbackException(I18nStringResourceManager.GetErrorMesg("FAIL_CONV_TO_UNICODE"));
					}
					num4 = ((bytes[i] << 8) & 0xFF00) | (bytes[i + 1] & 0xFF);
					i++;
					flag = true;
				}
				int num5 = (num4 >> 8) & 0xFF;
				int num6 = num4 & 0xFF;
				int num7 = ((m_ucsCharLevel1[num5] == '\uffff' || m_ucsCharLevel2[m_ucsCharLevel1[num5] + num6] == 65535) ? m_ucsCharReplacement : m_ucsCharLevel2[m_ucsCharLevel1[num5] + num6]);
				if ((num7 & 0xFFFFFFFFu) > 65535)
				{
					if (num2 + 1 >= num3)
					{
						if (flag)
						{
							i--;
						}
						break;
					}
					chars[num2++] = (char)(num7 >> 16);
					chars[num2++] = (char)((uint)num7 & 0xFFFFu);
				}
				else
				{
					chars[num2++] = (char)num7;
				}
			}
			charCount = num2 - charOffset;
			return i - offset;
		}

		public override int ConvertBytesToUTF16(byte[] bytes, int offset, int count, byte[] utfbytes, int utfOffset, ref int utfCount, bool ccb)
		{
			int i = offset;
			if (i < 0)
			{
				i = 0;
			}
			int num = i + count;
			if (num > bytes.Length)
			{
				num = bytes.Length;
			}
			int num2 = utfOffset;
			if (num2 < 0)
			{
				num2 = 0;
			}
			int num3 = num2 + utfCount;
			if (num3 > utfbytes.Length)
			{
				num3 = utfbytes.Length;
			}
			for (; i < num; i++)
			{
				if (num2 + 1 >= num3)
				{
					break;
				}
				bool flag = false;
				int num4 = bytes[i] & 0xFF;
				if (num4 > MAX_7_8_BIT)
				{
					if (i >= num - 1)
					{
						if (ccb)
						{
							break;
						}
						throw new DecoderFallbackException(I18nStringResourceManager.GetErrorMesg("FAIL_CONV_TO_UNICODE"));
					}
					num4 = ((bytes[i] << 8) & 0xFF00) | (bytes[i + 1] & 0xFF);
					i++;
					flag = true;
				}
				int num5 = (num4 >> 8) & 0xFF;
				int num6 = num4 & 0xFF;
				int num7 = ((m_ucsCharLevel1[num5] == '\uffff' || m_ucsCharLevel2[m_ucsCharLevel1[num5] + num6] == 65535) ? m_ucsCharReplacement : m_ucsCharLevel2[m_ucsCharLevel1[num5] + num6]);
				if ((num7 & 0xFFFFFFFFu) > 65535)
				{
					if (num2 + 3 >= num3)
					{
						if (flag)
						{
							i--;
						}
						break;
					}
					char[] array = new char[2]
					{
						(char)(num7 >> 16),
						(char)((uint)num7 & 0xFFFFu)
					};
					utfbytes[num2++] = (byte)(array[0] & 0xFFu);
					utfbytes[num2++] = (byte)((int)array[0] >> 8);
					utfbytes[num2++] = (byte)(array[1] & 0xFFu);
					utfbytes[num2++] = (byte)((int)array[1] >> 8);
				}
				else
				{
					utfbytes[num2++] = (byte)((ushort)num7 & 0xFFu);
					utfbytes[num2++] = (byte)((ushort)num7 >> 8);
				}
			}
			utfCount = num2 - utfOffset;
			return i - offset;
		}

		public override int ConvertCharsToBytes(char[] chars, int chars_offset, int chars_count, byte[] bytes, int bytes_begin, ref int bytes_count, bool bUseReplacementChar)
		{
			int num = chars_offset;
			int num2 = chars_offset + chars_count;
			char c = '\uffff';
			if (num < 0)
			{
				num = 0;
			}
			if (num2 > chars.Length)
			{
				num2 = chars.Length;
			}
			if (bytes_begin < 0)
			{
				bytes_begin = 0;
			}
			int num3 = bytes_begin + bytes_count;
			if (num3 > bytes.Length)
			{
				num3 = bytes.Length;
			}
			int num4 = bytes_begin;
			int i;
			for (i = num; i < num2 && num4 < num3; i++)
			{
				bool flag = false;
				if (chars[i] >= '\ud800' && chars[i] < '\udc00')
				{
					if (i + 1 >= num2 || chars[i + 1] < '\udc00' || chars[i + 1] > '\udfff')
					{
						if (num4 + 1 >= num3)
						{
							break;
						}
						bytes[num4++] = (byte)((int)m_2ByteOraCharReplacement[0] >> 8);
						bytes[num4++] = (byte)m_2ByteOraCharReplacement[0];
						continue;
					}
					c = ToOracleCharacter(chars[i], chars[i + 1], bUseReplacementChar);
					flag = true;
					i++;
				}
				else
				{
					int num5 = ((int)chars[i] >> 8) & 0xFF;
					int num6 = chars[i] & 0xFF;
					if (m_oraCharLevel1[num5] != 65535 && m_oraCharLevel2[m_oraCharLevel1[num5] + num6] != '\uffff')
					{
						c = m_oraCharLevel2[m_oraCharLevel1[num5] + num6];
					}
					if (c == '\uffff')
					{
						if (!bUseReplacementChar)
						{
							throw new DecoderFallbackException(I18nStringResourceManager.GetErrorMesg("FAIL_CONV_TO_BYTES"));
						}
						c = ((chars[i] <= '\u2fff') ? m_1ByteOraCharReplacement : m_2ByteOraCharReplacement[0]);
					}
				}
				if ((int)c >> 8 != 0)
				{
					if (num4 + 1 >= num3)
					{
						if (flag)
						{
							i--;
						}
						break;
					}
					bytes[num4++] = (byte)((int)c >> 8);
					bytes[num4++] = (byte)c;
				}
				else
				{
					bytes[num4++] = (byte)c;
				}
			}
			bytes_count = num4 - bytes_begin;
			return i - num;
		}

		public override int ConvertUTF16ToBytes(byte[] utf16Bytes, int utf16BytesOffset, int utf16BytesCount, byte[] bytes, int byteOffset, ref int byteCount, bool bUseReplacementChar = true)
		{
			int num = utf16BytesOffset;
			int num2 = utf16BytesOffset + utf16BytesCount;
			if (num < 0)
			{
				num = 0;
			}
			if (num2 > utf16Bytes.Length)
			{
				num2 = utf16Bytes.Length;
			}
			if (byteOffset < 0)
			{
				byteOffset = 0;
			}
			int num3 = byteOffset + byteCount;
			if (num3 > bytes.Length)
			{
				num3 = bytes.Length;
			}
			char c = '\uffff';
			int num4 = byteOffset;
			int i;
			for (i = num; i < num2 - 1 && num4 < num3; i += 2)
			{
				bool flag = false;
				int num5 = (utf16Bytes[i + 1] << 8) | utf16Bytes[i];
				if (num5 >= 55296 && num5 < 56320)
				{
					if (i + 3 >= num2)
					{
						if (num4 + 1 >= num3)
						{
							break;
						}
						bytes[num4++] = (byte)((int)m_2ByteOraCharReplacement[0] >> 8);
						bytes[num4++] = (byte)m_2ByteOraCharReplacement[0];
						continue;
					}
					int num6 = (utf16Bytes[i + 3] << 8) | utf16Bytes[i + 2];
					if (num6 >= 56320 && num6 <= 57343)
					{
						c = ToOracleCharacter((char)num5, (char)num6, bUseReplacementChar);
						flag = true;
						i += 2;
					}
				}
				else
				{
					int num7 = ((ushort)num5 >> 8) & 0xFF;
					int num8 = (ushort)num5 & 0xFF;
					if (m_oraCharLevel1[num7] != 65535 && m_oraCharLevel2[m_oraCharLevel1[num7] + num8] != '\uffff')
					{
						c = m_oraCharLevel2[m_oraCharLevel1[num7] + num8];
					}
					if (c == '\uffff')
					{
						if (!bUseReplacementChar)
						{
							throw new DecoderFallbackException(I18nStringResourceManager.GetErrorMesg("FAIL_CONV_TO_BYTES"));
						}
						c = (((ushort)num5 <= 12287) ? m_1ByteOraCharReplacement : m_2ByteOraCharReplacement[0]);
					}
				}
				if ((int)c >> 8 != 0)
				{
					if (num4 + 1 >= num3)
					{
						if (flag)
						{
							i -= 2;
						}
						break;
					}
					bytes[num4++] = (byte)((int)c >> 8);
					bytes[num4++] = (byte)c;
				}
				else
				{
					bytes[num4++] = (byte)c;
				}
			}
			byteCount = num4 - byteOffset;
			return i - num;
		}

		public override int ConvertStringToBytes(string chars, int chars_offset, int chars_count, byte[] bytes, int bytes_begin, ref int bytes_count, bool bUseReplacementChar)
		{
			int num = chars_offset;
			int num2 = chars_offset + chars_count;
			char c = '\uffff';
			if (num < 0)
			{
				num = 0;
			}
			if (num2 > chars.Length)
			{
				num2 = chars.Length;
			}
			if (bytes_begin < 0)
			{
				bytes_begin = 0;
			}
			int num3 = bytes_begin + bytes_count;
			if (num3 > bytes.Length)
			{
				num3 = bytes.Length;
			}
			int num4 = bytes_begin;
			int i;
			for (i = num; i < num2 && num4 < num3; i++)
			{
				bool flag = false;
				if (chars[i] >= '\ud800' && chars[i] < '\udc00')
				{
					if (i + 1 >= num2 || chars[i + 1] < '\udc00' || chars[i + 1] > '\udfff')
					{
						if (num4 + 1 >= num3)
						{
							break;
						}
						bytes[num4++] = (byte)((int)m_2ByteOraCharReplacement[0] >> 8);
						bytes[num4++] = (byte)m_2ByteOraCharReplacement[0];
						continue;
					}
					c = ToOracleCharacter(chars[i], chars[i + 1], bUseReplacementChar);
					flag = true;
					i++;
				}
				else
				{
					int num5 = ((int)chars[i] >> 8) & 0xFF;
					int num6 = chars[i] & 0xFF;
					if (m_oraCharLevel1[num5] != 65535 && m_oraCharLevel2[m_oraCharLevel1[num5] + num6] != '\uffff')
					{
						c = m_oraCharLevel2[m_oraCharLevel1[num5] + num6];
					}
					if (c == '\uffff')
					{
						if (!bUseReplacementChar)
						{
							throw new DecoderFallbackException(I18nStringResourceManager.GetErrorMesg("FAIL_CONV_TO_BYTES"));
						}
						c = ((chars[i] <= '\u2fff') ? m_1ByteOraCharReplacement : m_2ByteOraCharReplacement[0]);
					}
				}
				if ((int)c >> 8 != 0)
				{
					if (num4 + 1 >= num3)
					{
						if (flag)
						{
							i--;
						}
						break;
					}
					bytes[num4++] = (byte)((int)c >> 8);
					bytes[num4++] = (byte)c;
				}
				else
				{
					bytes[num4++] = (byte)c;
				}
			}
			bytes_count = num4 - bytes_begin;
			return i - num;
		}

		protected virtual int ConvertByteArraySegListToCharsImpl<T>(IList<ArraySegment<byte>> bytes, int bytesOffset, int bytesCount, T[] chars, int charOffset, ref int charCount, bool bUseReplacementChar, ConvertByteToCharsDelegate<T> t)
		{
			int num = charOffset;
			int charCount2 = charCount;
			int num2 = 0;
			int num3 = 0;
			int num4 = 0;
			byte[] array = null;
			int num5 = 0;
			int idx = 0;
			int offSet = bytes[0].Offset;
			bool flag = false;
			if (bytesOffset > 0)
			{
				UTF16ConvUtility.GetSegementIndices(bytes, bytesOffset, ref idx, ref offSet);
			}
			for (int i = idx; i < bytes.Count; i++)
			{
				if (flag)
				{
					break;
				}
				if (charCount2 <= 0)
				{
					break;
				}
				int num6 = bytes[i].Offset + num4;
				int num7 = bytes[i].Count - num4;
				if (i == idx)
				{
					num6 = offSet + num4;
					num7 = bytes[i].Count - (offSet - bytes[i].Offset) - num4;
				}
				if (bytesCount - num3 <= num7)
				{
					num7 = bytesCount - num3;
					flag = true;
				}
				int num8 = t(bytes[i].Array, num6, num7, chars, num, ref charCount2, bUseReplacementChar);
				num3 += num8;
				num += charCount2;
				num2 += charCount2;
				charCount2 = charCount - num2;
				if (charCount2 > 0 && num8 < num7 && !flag && i < bytes.Count - 1)
				{
					if (array == null)
					{
						array = new byte[2];
					}
					byte[] array2 = bytes[i + 1].Array;
					int num9 = num6 + num8;
					array[0] = bytes[i].Array[num9];
					array[1] = array2[bytes[i + 1].Offset];
					num4 = 1;
					num5 = 2;
					num8 = t(array, 0, num5, chars, num, ref charCount2, bUseReplacementChar);
					if (num8 == 0)
					{
						break;
					}
					num3 += num8;
					num += charCount2;
					num2 += charCount2;
					charCount2 = charCount - num2;
				}
				else
				{
					num4 = 0;
				}
			}
			charCount = num2;
			return num3;
		}

		public override int ConvertBytesToChars(IList<ArraySegment<byte>> bytes, int bytesOffset, int bytesCount, char[] chars, int charOffset, ref int charCount, bool bUseReplacementChar)
		{
			if (bytes.Count == 1)
			{
				return ConvertBytesToChars(bytes[0].Array, bytes[0].Offset + bytesOffset, bytesCount, chars, charOffset, ref charCount, bUseReplacementChar);
			}
			return ConvertByteArraySegListToCharsImpl(bytes, bytesOffset, bytesCount, chars, charOffset, ref charCount, bUseReplacementChar, ConvertBytesToChars);
		}
	}
}
